#include "wx/wxprec.h"
#include "wx/frame.h"

#if wxUSE_MENUS && wxUSE_STATUSBAR

BEGIN_EVENT_TABLE( wxFrameBase, wxTopLevelWindow )
  EVT_MENU_OPEN( wxFrameBase::OnMenuOpen )
  EVT_MENU_CLOSE( wxFrameBase::OnMenuClose )

  EVT_MENU_HIGHLIGHT_ALL( wxFrameBase::OnMenuHighlight )
END_EVENT_TABLE()

#endif // wxUSE_MENUS && wxUSE_STATUSBAR

wxFrameBase::wxFrameBase() {
  m_frameMenuBar = NULL;
  #if wxUSE_TOOLBAR
  m_frameToolBar = NULL;
  #endif // wxUSE_TOOLBAR
  #if wxUSE_STATUSBAR
  m_frameStatusBar = NULL;
  #endif // wxUSE_STATUSBAR
  m_statusBarPane = 0;
}

wxFrameBase::~wxFrameBase() {
  // this destructor is required for Darwin
}

wxFrame *wxFrameBase::New( wxWindow *parent,
                           wxWindowID id,
                           const wxString& title,
                           const wxPoint& pos,
                           const wxSize& size,
                           long style,
                           const wxString& name ) {
  return new wxFrame( parent, id, title, pos, size, style, name );
}

void wxFrameBase::DeleteAllBars() {
  if( m_frameMenuBar ) {
    delete m_frameMenuBar;
    m_frameMenuBar = ( wxMenuBar * ) NULL;
  }
  #if wxUSE_STATUSBAR
  if( m_frameStatusBar ) {
    delete m_frameStatusBar;
    m_frameStatusBar = ( wxStatusBar * ) NULL;
  }
  #endif // wxUSE_STATUSBAR
  #if wxUSE_TOOLBAR
  if( m_frameToolBar ) {
    delete m_frameToolBar;
    m_frameToolBar = ( wxToolBar * ) NULL;
  }
  #endif // wxUSE_TOOLBAR
}

bool wxFrameBase::IsOneOfBars( const wxWindow *win ) const {
  if( win == GetMenuBar() ) {
    return true;
  }
  #if wxUSE_STATUSBAR
  if( win == GetStatusBar() ) {
    return true;
  }
  #endif // wxUSE_STATUSBAR
  #if wxUSE_TOOLBAR
  if( win == GetToolBar() ) {
    return true;
  }
  #endif // wxUSE_TOOLBAR
  return false;
}

wxPoint wxFrameBase::GetClientAreaOrigin() const {
  wxPoint pt = wxTopLevelWindow::GetClientAreaOrigin();
  #if wxUSE_TOOLBAR && !defined(__WXUNIVERSAL__)
  wxToolBar *toolbar = GetToolBar();
  if( toolbar && toolbar->IsShown() ) {
    int w, h;
    toolbar->GetSize( &w, &h );
    if( toolbar->GetWindowStyleFlag() & wxTB_VERTICAL ) {
      pt.x += w;
    } else
    { pt.y += h; }
  }
  #endif // wxUSE_TOOLBAR
  return pt;
}

void wxFrameBase::SendSizeEvent() {
  const wxSize size = GetSize();
  wxSizeEvent event( size, GetId() );
  event.SetEventObject( this );
  GetEventHandler()->AddPendingEvent( event );
  ( ( wxFrame* )this )->GtkOnSize();
}

bool wxFrameBase::ProcessCommand( int id ) {
  wxMenuBar *bar = GetMenuBar();
  if( !bar ) {
    return false;
  }
  wxCommandEvent commandEvent( wxEVT_COMMAND_MENU_SELECTED, id );
  commandEvent.SetEventObject( this );
  wxMenuItem *item = bar->FindItem( id );
  if( item ) {
    if( !item->IsEnabled() ) {
      return true;
    }
    if( ( item->GetKind() == wxITEM_RADIO ) && item->IsChecked() ) {
      return true;
    }
    if( item->IsCheckable() ) {
      item->Toggle();
      // use the new value
      commandEvent.SetInt( item->IsChecked() );
    }
  }
  return GetEventHandler()->ProcessEvent( commandEvent );
}

void wxFrameBase::UpdateWindowUI( long flags ) {
  wxWindowBase::UpdateWindowUI( flags );
  #if wxUSE_TOOLBAR
  if( GetToolBar() ) {
    GetToolBar()->UpdateWindowUI( flags );
  }
  #endif
  if( GetMenuBar() ) {
    if( ( flags & wxUPDATE_UI_FROMIDLE ) && !wxUSE_IDLEMENUUPDATES ) {
      // If coming from an idle event, we only
      // want to update the menus if we're
      // in the wxUSE_IDLEMENUUPDATES configuration:
      // so if we're not, do nothing
    } else
    { DoMenuUpdates(); }
  }
}

// ----------------------------------------------------------------------------
// event handlers for status bar updates from menus
// ----------------------------------------------------------------------------

#if wxUSE_MENUS && wxUSE_STATUSBAR

void wxFrameBase::OnMenuHighlight( wxMenuEvent& event ) {
  #if wxUSE_STATUSBAR
  ( void )ShowMenuHelp( GetStatusBar(), event.GetMenuId() );
  #endif // wxUSE_STATUSBAR
}

#if !wxUSE_IDLEMENUUPDATES
void wxFrameBase::OnMenuOpen( wxMenuEvent& event )
#else
void wxFrameBase::OnMenuOpen( wxMenuEvent& ( event ) )
#endif
{
  #if !wxUSE_IDLEMENUUPDATES
  DoMenuUpdates( event.GetMenu() );
  #endif // !wxUSE_IDLEMENUUPDATES
}

void wxFrameBase::OnMenuClose( wxMenuEvent& ( event ) ) {
  // do we have real status text to restore?
  if( !m_oldStatusText.empty() ) {
    if( m_statusBarPane >= 0 ) {
      wxStatusBar *statbar = GetStatusBar();
      if( statbar ) {
        statbar->SetStatusText( m_oldStatusText, m_statusBarPane );
      }
    }
    m_oldStatusText.clear();
  }
}

#endif // wxUSE_MENUS && wxUSE_STATUSBAR

// Implement internal behaviour (menu updating on some platforms)
void wxFrameBase::OnInternalIdle() {
  wxTopLevelWindow::OnInternalIdle();
  #if wxUSE_MENUS && wxUSE_IDLEMENUUPDATES
  if( wxUpdateUIEvent::CanUpdate( this ) ) {
    DoMenuUpdates();
  }
  #endif
}

// ----------------------------------------------------------------------------
// status bar stuff
// ----------------------------------------------------------------------------

#if wxUSE_STATUSBAR

wxStatusBar* wxFrameBase::CreateStatusBar( int number,
    long style,
    wxWindowID id,
    const wxString& name ) {
  // the main status bar can only be created once (or else it should be
  // deleted before calling CreateStatusBar() again)
  wxCHECK_MSG( !m_frameStatusBar, ( wxStatusBar * )NULL,
               wxT( "recreating status bar in wxFrame" ) );
  SetStatusBar( OnCreateStatusBar( number, style, id, name ) );
  return m_frameStatusBar;
}

wxStatusBar *wxFrameBase::OnCreateStatusBar( int number,
    long style,
    wxWindowID id,
    const wxString& name ) {
  wxStatusBar *statusBar = new wxStatusBar( this, id, style, name );
  statusBar->SetFieldsCount( number );
  return statusBar;
}

void wxFrameBase::SetStatusText( const wxString& text, int number ) {
  wxCHECK_RET( m_frameStatusBar != NULL, wxT( "no statusbar to set text for" ) );
  m_frameStatusBar->SetStatusText( text, number );
}

void wxFrameBase::SetStatusWidths( int n, const int widths_field[] ) {
  wxCHECK_RET( m_frameStatusBar != NULL, wxT( "no statusbar to set widths for" ) );
  m_frameStatusBar->SetStatusWidths( n, widths_field );
  PositionStatusBar();
}

void wxFrameBase::PushStatusText( const wxString& text, int number ) {
  wxCHECK_RET( m_frameStatusBar != NULL, wxT( "no statusbar to set text for" ) );
  m_frameStatusBar->PushStatusText( text, number );
}

void wxFrameBase::PopStatusText( int number ) {
  wxCHECK_RET( m_frameStatusBar != NULL, wxT( "no statusbar to set text for" ) );
  m_frameStatusBar->PopStatusText( number );
}

bool wxFrameBase::ShowMenuHelp( wxStatusBar *( statbar ), int menuId ) {
  wxString helpString;
  bool show = menuId != wxID_SEPARATOR && menuId != -2 /* wxID_TITLE */;
  if( show ) {
    wxMenuBar *menuBar = GetMenuBar();
    if( menuBar ) {
      // it's ok if we don't find the item because it might belong
      // to the popup menu
      wxMenuItem *item = menuBar->FindItem( menuId );
      if( item ) {
        helpString = item->GetHelp();
      }
    }
  }
  DoGiveHelp( helpString, show );
  return !helpString.empty();
}

void wxFrameBase::SetStatusBar( wxStatusBar *statBar ) {
  bool hadBar = m_frameStatusBar != NULL;
  m_frameStatusBar = statBar;
  if( ( m_frameStatusBar != NULL ) != hadBar ) {
    PositionStatusBar();
    DoLayout();
  }
}

#endif // wxUSE_STATUSBAR

#if wxUSE_MENUS || wxUSE_TOOLBAR
void wxFrameBase::DoGiveHelp( const wxString& text, bool show ) {
  #if wxUSE_STATUSBAR
  if( m_statusBarPane < 0 ) {
    // status bar messages disabled
    return;
  }
  wxStatusBar *statbar = GetStatusBar();
  if( !statbar ) {
    return;
  }
  wxString help;
  if( show ) {
    help = text;
    // remember the old status bar text if this is the first time we're
    // called since the menu has been opened as we're going to overwrite it
    // in our DoGiveHelp() and we want to restore it when the menu is
    // closed
    //
    // note that it would be logical to do this in OnMenuOpen() but under
    // MSW we get an EVT_MENU_HIGHLIGHT before EVT_MENU_OPEN, strangely
    // enough, and so this doesn't work and instead we use the ugly trick
    // with using special m_oldStatusText value as "menu opened" (but it is
    // arguably better than adding yet another member variable to wxFrame
    // on all platforms)
    if( m_oldStatusText.empty() ) {
      m_oldStatusText = statbar->GetStatusText( m_statusBarPane );
      if( m_oldStatusText.empty() ) {
        // use special value to prevent us from doing this the next time
        m_oldStatusText += _T( '\0' );
      }
    }
  } else { // hide the status bar text
    // i.e. restore the old one
    help = m_oldStatusText;
    // make sure we get the up to date text when showing it the next time
    m_oldStatusText.clear();
  }
  statbar->SetStatusText( help, m_statusBarPane );
  #else
  wxUnusedVar( text );
  wxUnusedVar( show );
  #endif // wxUSE_STATUSBAR
}
#endif // wxUSE_MENUS || wxUSE_TOOLBAR

#if wxUSE_TOOLBAR

wxToolBar* wxFrameBase::CreateToolBar( long style,
                                       wxWindowID id,
                                       const wxString& name ) {
  // the main toolbar can't be recreated (unless it was explicitly deleted
  // before)
  wxCHECK_MSG( !m_frameToolBar, ( wxToolBar * )NULL,
               wxT( "recreating toolbar in wxFrame" ) );
  if( style == -1 ) {
    style = wxBORDER_NONE | wxTB_HORIZONTAL | wxTB_FLAT;
  }
  SetToolBar( OnCreateToolBar( style, id, name ) );
  return m_frameToolBar;
}

wxToolBar* wxFrameBase::OnCreateToolBar( long style,
    wxWindowID id,
    const wxString& name ) {
  #if defined(__WXWINCE__) && defined(__POCKETPC__)
  return new wxToolMenuBar( this, id,
                            wxDefaultPosition, wxDefaultSize,
                            style, name );
  #else
  return new wxToolBar( this, id,
                        wxDefaultPosition, wxDefaultSize,
                        style, name );
  #endif
}

void wxFrameBase::SetToolBar( wxToolBar *toolbar ) {
  bool hadBar = m_frameToolBar != NULL;
  m_frameToolBar = toolbar;
  if( ( m_frameToolBar != NULL ) != hadBar ) {
    PositionToolBar();
    DoLayout();
  }
}

#endif // wxUSE_TOOLBAR

void wxFrameBase::DoMenuUpdates( wxMenu* menu ) {
  if( menu ) {
    wxEvtHandler* source = GetEventHandler();
    menu->UpdateUI( source );
  } else {
    wxMenuBar* bar = GetMenuBar();
    if( bar != NULL ) {
      bar->UpdateMenus();
    }
  }
}

void wxFrameBase::DetachMenuBar() {
  if( m_frameMenuBar ) {
    m_frameMenuBar->Detach();
    m_frameMenuBar = NULL;
  }
}

void wxFrameBase::AttachMenuBar( wxMenuBar *menubar ) {
  if( menubar ) {
    menubar->Attach( ( wxFrame * )this );
    m_frameMenuBar = menubar;
  }
}

void wxFrameBase::SetMenuBar( wxMenuBar *menubar ) {
  if( menubar == GetMenuBar() ) {
    // nothing to do
    return;
  }
  DetachMenuBar();
  this->AttachMenuBar( menubar );
}
